#!/usr/bin/guile \
-e main -s
!#

;; use these modules to help my process the command line arguments.
(use-modules (ice-9 getopt-long))

(define (fibonaci n)
  (cond
   ((= n 0) 0)
   ((= n 1) 1)
   (else
    (+ (fibonaci (- n 1))
       (fibonaci (- n 2))))))

;;; (fibonaci 4)
;;; (+ (fibonaci 3)                                     (fibonaci 2))
;;; (+ (+ (fibonaci 2)                (fibonaci 1))  (+ (fibonaci 1) (fibonaci 0)))
;;; (+ (+ (fibonaci 1) (fibonaci 0))  1              (+ 1             1))
;;; (+ (+ 1            1              1               2))


;; the following two fibonaci-iter are two iterative processes
(define (fibonaci-iter n)
  (fib-iter 0 1 n))

(define (fib-iter a b count)
  (if (= count 0)
      b
      (fib-iter (+ a b) a (- count 1))))


(define (fibonaci-iter n)
  (let fib-iter ((a 0) (b 1) (count n))
    (if (= count 0)
        b
        (fib-iter (+ a b) a (- count 1)))))

;;This function takes a string an input and outputs a boolean.
(define (inputIsNumber? x)
  (number? (string->number x)))

(define (main args)
  (let* ((option-spec '((version (single-char #\v) (value #f))
                        (help    (single-char #\h) (value #f))
                        ;;Adding in a option to specify a specific fibonacci number
                        ;; value t means that the program expects a value, if it does not receive a value
                        ;; then getopt-long will signal an error.
                        ;; single char means that --number 5 == -n 5
                        ;; predicate calls the function inputIsNumber of the string after -n or --number
                        (number  (single-char #\n) (value #t)
                                 ;;(predicate inputIsNumber?)
                                 )
                        ))
         (options (getopt-long args option-spec))
         (help-wanted (option-ref options 'help #f))
         (version-wanted (option-ref options 'version #f))
         (number-wanted (option-ref options 'number #f)))
    (if (or version-wanted help-wanted number-wanted)
        (begin
          (if version-wanted
              (display "Fibonacci version 0.1\n"))
          (if help-wanted
              (display "\
     Fibonacci options [options]
       -v, --version    Display version
       -h, --help       Display this help
       -n, --number     Display the nth fibonacci number.
     "))
          (if number-wanted
              (display (fibonaci (string->number number-wanted))))
          )
        (begin
          (display "Hello, World!") (newline)))))
